<html>

<head>
    <title>10进制转64进制</title>
    <style>
        ul li {
            display: inline-block;
        }
    </style>
</head>

<body>
    <div id="input">
        <h3>64位对应值关系：</h3>
        <ul id="scaleDesc"></ul>
    </div>
    <br />
    <div>
        <h3>10进制转64：</h3>
        <input id="input10" type="text" /> <button id="btn10">转换</button><br />
        <span id="rst10"></span>
    </div>
    <br />
    <div>
        <h3>64进制转10：</h3>
        <div>
            <input id="input64" type="text" /><button id="btn64">转换</button><br />
            <span id="rst64"></span>
        </div>
    </div>
    <div id="rst"></div>
</body>
<script>
    function Scale64() {
        const SCALE = 64; // 位数
        const TIMES = 15; // 小数精度位数
        const NUMBER_SCALE_MAP = [
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
            'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
            'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
            'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
            'Y', 'Z', '^', '$'
        ];

        const SCALE_NUMBER_MAP = NUMBER_SCALE_MAP.reduce((acc, item, index) => {
            acc[item] = index;
            return acc;
        }, {});

        this.integerTo64 = function (n) {
            let nCopy = Number(n);
            const remainders = [];
            while (nCopy / SCALE) {
                let remainder = nCopy % SCALE;
                nCopy = (nCopy - remainder) / SCALE;
                remainders.unshift(NUMBER_SCALE_MAP[remainder])
            }
            return remainders.join('');
        };

        this.integerTo64Reverse = function (n) {
            var nCopy = String(n);
            return nCopy.split('').reverse().reduce((acc, item, index) => {
                acc += SCALE_NUMBER_MAP[item] * (SCALE ** index);
                return acc
            }, 0)
        };

        this.decimalTo64 = function (n) {
            // 0 < n < 1
            const arr = [];
            let nCopy = Number(n);
            for (let i = 0; i < TIMES; i++) {
                nCopy = nCopy * SCALE;

                const parts = String(nCopy).split('.');
                // 是否是整数
                if (parts.length === 1) {
                    arr.push(NUMBER_SCALE_MAP[parts[0]])
                    break;
                }
                const integerPart = parts[0];
                const decimalPart = parts[1];
                if (Number(integerPart) > 0) {
                    arr.push(NUMBER_SCALE_MAP[Number(integerPart)])
                    nCopy = Number('0.' + decimalPart);
                } else {
                    arr.push(NUMBER_SCALE_MAP[0])
                }
            }
            return arr.join('');
        };

        this.decimalTo64Reverse = function (n) {
            var nCopy = String(n);
            return nCopy.split('').reduce((acc, item, index) => {
                acc += SCALE_NUMBER_MAP[item] * (SCALE ** (-index - 1));
                return acc;
            }, 0)
        };

        this.to64 = function (n) {
            const nCopy = Number(n);

            if (nCopy < 1) {
                return '0.' + this.decimalTo64(nCopy)
            }

            if (nCopy === 1) {
                return '1'
            }

            const [integer, decimal] = String(n).split('.');
            if (decimal === undefined) {
                return this.integerTo64(integer)
            }
            return this.integerTo64(integer) + '.' + this.decimalTo64('0.' + decimal)
        };

        this.to64Reverse = function (n) {
            // 字符串统一处理 -- 有可能存在字母
            if (n.includes('.')) {
                const [integer, decimal] = n.split('.');
                return this.integerTo64Reverse(integer) + this.decimalTo64Reverse(decimal)
            }
            return this.integerTo64Reverse(n);
        }

        this.getScale = function () {
            return SCALE;
        };

        this.getNumberScaleMap = function () {
            return NUMBER_SCALE_MAP;
        }
    }
    /* 测试数据 TODO: */

    const scale = new Scale64();
    const NUMBER_SCALE_MAP = scale.getNumberScaleMap();

    document.querySelector('#scaleDesc').innerHTML = NUMBER_SCALE_MAP.map(function (item, index) {
        return `<li>${index}: ${item} &nbsp;&nbsp;</li>${index % 10 === 0 ? '<br/>' : ''}`
    }).join('');

    document.querySelector('#btn10').onclick = function () {
        const input = document.querySelector('#input10').value;
        document.querySelector('#rst10').innerHTML = scale.to64(input);
    }
    document.querySelector('#btn64').onclick = function () {
        const input = document.querySelector('#input64').value;
        document.querySelector('#rst64').innerHTML = scale.to64Reverse(input);
    }

</script>

</html>